<?php
class DB {
	public static 	$dbh,
					$dbh2,
					$dbh3,
					$mch,
					$inited = false,
					$inited3 = false,
					$inited2 = false,
					$rpl;

	public static function Connect(){
		if(!self::$inited){
			$dsn = DB_TYPE. ':' . 'dbname=' . DB_NAME. ';' . 'host=' . DB_HOST. ';' . 'port=' . DB_PORT;
	    	try {
	        	self::$dbh = new MY_PDO($dsn, DB_USER, DB_PASS, array(PDO::ATTR_PERSISTENT => true));
	        	self::$dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
	        	
	        	$stmt=self::$dbh->prepare("SET client_encoding TO 'UTF8'");
              	$stmt->execute(Array());

	        	
	    	} catch(PDOException $e) {
	        	die("DB ERROR: " . $e->getMessage() . ' ' . $e->getCode());
	   		}

	    	self::$mch = new Memcache;
	    	@self::$mch->pconnect(MC_HOST, MC_PORT);
			self::$inited = true;
		}
	}

	public static function db2(){
		if(!self::$inited2){
			$dsn = 'pgsql:dbname=buscan_db;host=78.110.52.165;port=5439';
	        try
	        {
	            self::$dbh2 = new PDO($dsn, "manfredi", "XUXP8Umg", array(PDO::ATTR_PERSISTENT => true));
	            self::$dbh2->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
	        }
	        catch(PDOException $e)
	        {
	            die("DB ERROR: " . $e->getMessage() . ' ' . $e->getCode());
	        }
			self::$inited2 = true;
		}
		return self::$dbh2;
	}
	public static function db3(){
		if(!self::$inited3){
			$dsn = 'pgsql:dbname=buscan_db2;host=78.110.52.165;port=5439';
	        try
	        {
	            self::$dbh3 = new PDO($dsn, "manfredi", "XUXP8Umg", array(PDO::ATTR_PERSISTENT => true));
	            self::$dbh3->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
	        }
	        catch(PDOException $e)
	        {
	            die("DB ERROR: " . $e->getMessage() . ' ' . $e->getCode());
	        }
			self::$inited3 = true;
		}
		return self::$dbh3;
	}


	// Объект базы данных
	public static function getDBH(){
		if(!self::$inited){
			self::Connect();
		}
		return self::$dbh;
	}
	
	
	public static function getRPL(){
		if(! (self::$rpl instanceof Realplexor)){
			self::$rpl = new Realplexor(RPL_HOST, RPL_PORT, RPL_NAMESPACE);
		}
		return self::$rpl;
	}
	
	// Объект мемкеша
	public static function getMCH(){
		if(!self::$inited){
			self::Connect();
		}
		return self::$mch;
	}


	public static function generateAllClassFromDB()
	{
		$sql = "SELECT "
			. " c.relname AS table_name"
			. " FROM pg_class c, pg_user u"
			. " WHERE "
			. "c.relowner = u.usesysid"
			. " AND "
			. "c.relkind = 'r'"
			. " AND "
			. "NOT EXISTS (SELECT 1 FROM pg_views WHERE viewname = c.relname)"
			. " AND "
			. "c.relname !~ '^(pg_|sql_)'"
			. " UNION "
			. "SELECT "
			. " c.relname AS table_name"
			. " FROM pg_class c"
			. " WHERE "
			. "c.relkind = 'r'"
			. " AND "
			. "NOT EXISTS (SELECT 1 FROM pg_views WHERE viewname = c.relname)"
			. " AND "
			. "NOT EXISTS (SELECT 1 FROM pg_user WHERE usesysid = c.relowner)"
			. " AND "
			. "c.relname !~ '^pg_'";
		$sth = self::getDBH()->query($sql);
		while($row = $sth->fetch(PDO::FETCH_ASSOC))
		{
			self::createClassFromDB($row['table_name']);
		}
	}



	public static function createClassFromDB($className = null)
	{
		$mapTypesDb2Php = Array(
					'integer'    => 'int',
					'int2'       => 'int',
					'int4'       => 'int',
					'int8'       => 'int',
					'varchar'    => 'string',
					'text'       => 'string',
					'char'       => 'string',
					'bool'       => 'bool',
					'boolean'    => 'bool'
					);

		if($className)
		{
			/*$sth = $this->dbh->query('SELECT * FROM ' . $className . ' LIMIT 1');
			 $meta = array();
			 foreach(range(0, $sth->columnCount() - 1) as $i)
			 {
			 $meta[] = $sth->getColumnMeta($i);
			 }
			 var_dump($meta);
			 $sth = null;*/

			$sql = "SELECT"
				. " a.attnum,"
				. " a.attname AS field,"
				. " t.typname AS type,"
				. " format_type(a.atttypid, a.atttypmod) AS complete_type,"
				. " a.attnotnull AS isnotnull,"
				. " (SELECT 't' FROM pg_index WHERE c.oid = pg_index.indrelid AND pg_index.indkey[0] = a.attnum AND pg_index.indisprimary = 't') AS pri,"
				. " (SELECT pg_attrdef.adsrc FROM pg_attrdef WHERE c.oid = pg_attrdef.adrelid AND pg_attrdef.adnum=a.attnum) AS \"default\""
				. " FROM pg_attribute a, pg_class c, pg_type t"
				. " WHERE "
				. "c.relname = '". $className . "'"
				. " AND "
				. "a.attnum > 0"
				. " AND "
				. "a.attrelid = c.oid"
				. " AND "
				. "a.atttypid = t.oid"
				. " ORDER BY a.attnum"
				;
			$sth = self::getDBH()->query($sql);
			$meta = array();
			if($sth)
			{
				while($row = $sth->fetch(PDO::FETCH_ASSOC))
				{
					$meta[$row['field']] = $row;
				}
				var_dump($meta);
			}

			$tmpl = new vlibTemplate(CFG_MODELS_CLASSES . DIRECTORY_SEPARATOR . "model_template.php");
			$aTableColumns = Array();
			$aPKeys = array();
			$aSeqs = array();
			foreach($meta as $name => $attr)
			{
				$type = $mapTypesDb2Php[$attr['type']];
				$pk = ($attr['pri'] == 't');
				$comment = null;
				if($attr['pri'])
				{
					if(count($aPKeys))
					{
						echo ("Already has primary key " . $tbl_pk_key);
					}
					$aPKeys[$name] = Array('pk' => $name);
					$comment = " PRIMARY KEY ";
				}
				if($attr['default'])
				{
					$reg_matched = null;
					if(preg_match("/nextval\('(.+)'/", $attr['default'], $reg_matched))
					{
						$seq_name = $reg_matched[1];
						$aSeqs[$name] = Array('name' => $name, 'seq_name' => $seq_name);
						$comment .= " Sequense name: " . $seq_name;
					}
				}
				$aTableColumns[$name] =
					Array(
					      'name'	=> $name,
					      'type'	=> $type,
					      'pk'	=> $pk,
					      'comment'	=> $comment
					      );
			}
			$tmpl->setLoop('tbl_pk_key', $aPKeys);
			$tmpl->setLoop('tbl_pk_seq', $aSeqs);
			$tmpl->setLoop('tableColumns', $aTableColumns);
			$tmpl->setVar('className', $className);
			echo "<pre>\n";
			$tmpl->pparse();
			echo "</pre>";
			#die();
			$oldmask = umask(000);
			$fName = CFG_MODELS_CLASSES . DIRECTORY_SEPARATOR . $className;
			if(file_exists($fName . '.php')) $fName .= '___New';
			$fName .= '.php';
			file_put_contents($fName, "<?php\n" . $tmpl->grab() . "\n?>");
			chmod($fName, 0664);
			umask($oldmask);
		}
	}
	
	
	
	public static $online_key = Array(
		0 => "TW::online_0",
		1 => "TW::online_1",
		2 => "TW::online_2",
		3 => "TW::online_3",
		4 => "TW::online_4",
		5 => "TW::online_5"
	);
	public static function UserOnline(){
		$cnt = 0;
		$key = date("i") % 6;
		foreach(self::$online_key as $k => $v){
			if($key != $k){
				$cnt += self::getMCH()->get($v);
			}
		}
		return $cnt;
	}

   public static function UserOnlineIn(){
    	//$key = date("i") % 4;
    	$key = date("i") % 6;
		if(self::getMCH()->increment(self::$online_key[$key],1) === false){
			self::getMCH()->set(self::$online_key[$key],1,0, 60 * 5);
		}
		$_SESSION["tw_last_time_online"] = time();
		self::USerLogin();
    }
	
	 public static $userlogin_key= Array(
    							0=>"cnt_today",
    							1=>"cnt_repeated"
    						);
	public static function USerLogin(){
		if(!isset($_COOKIE["UserLogin"])){
			setcookie ("UserLogin", time(), time()+ 3600 * 48 );
			
			$key = 0;
			if(self::getMCH()->increment(self::$userlogin_key[$key],1) === false){
				self::getMCH()->set(self::$userlogin_key[$key], 1, 0, 3600 * 72);
			}
		}else{
			// Если я заходил. проверяем изменился ли день моего захода
			$d = date("D", $_COOKIE["UserLogin"]);
			// Если дни не совпадают, то
			if($d != date("D")){
				// Создаем куку о том что я зашел повторно

				// Проверяем попал ли я уже в этот счетчик
				if( $_COOKIE["UserLoginRep"] != $d) {
					// Ставим сегодняшнюю куку
					setcookie("UserLoginRep",date("D") , time() + 3600 * 24 );
					// Инкримент в повторные заходы
					$key = 1;
					if(self::getMCH()->increment(self::$userlogin_key[$key],1) === false){
						self::getMCH()->set(self::$userlogin_key[$key], 1, 0, 3600 * 72);
					}
					// Инкремент в сегодняшнии заходы
					$key = 0;
					if(self::getMCH()->increment(self::$userlogin_key[$key],1) === false){
						self::getMCH()->set(self::$userlogin_key[$key], 1, 0, 3600 * 72);
					}
					// Кука сегодняшнего захода
					setcookie ("UserLogin", time(), time()+ 3600 * 48 );
				}
			}
		}
	}
	
	//function __destruct(){
	//	
	//}
	
}

class MY_PDO extends PDO{
	public static $isTrance = false;
	public static $trancID = 0;
	public static $trancObject = Array();
	
	public function beginTransaction(){
		if(parent::beginTransaction()){
			MY_PDO::$isTrance = true;
			MY_PDO::$isTrance++;
			return true;
		}
		return false;
	}
	
	public function commit(){
		if( parent::commit() ){
			MY_PDO::$isTrance = false;
			$this->saveWorkObject();
			return true;
		}
	
	}
	
	private function saveWorkObject(){
		while($obj = array_shift(MY_PDO::$trancObject) ){
//			echo "Апдейт по транзакции<br />";
			$obj->saveToCache();
		}
	}
	public function rollBack(){
		if(MY_PDO::$isTrance){
			MY_PDO::$isTrance = false;
			MY_PDO::$trancObject = Array();
		}
		return parent::rollBack();
	}
	
}


?>
